<?php
/**
 *  @department : Commercial development.
 *  @description : This file is part of [example].
 *  example all rights reserved.
 */
namespace app\http;

use think\facade\Cache;
use think\swoole\Server;

/*
 * 基于Swoole实现的WebSocket管理控制
 * 服务端管控命令:
 * php think swoole:server
 * 支持reload|restart|stop|status 操作
 * php think swoole:server reload
 *
 * 应用场景: 多个客户端与服务器连接, 由服务器统一向客户端推送消息。
 */
class Swoole extends Server
{
    protected $host = '0.0.0.0';

    protected $port = 9508;

    protected $serverType = 'socket';

    protected $mode = SWOOLE_PROCESS;

    protected $sockType = SWOOLE_SOCK_TCP;

    protected $option = [
        'worker_num'  => 4,
        'max_request' => 10000,
        'daemonize'   => true,
        'backlog'     => 128,
        //心跳检测：每60秒遍历所有连接，强制关闭10分钟内没有向服务器发送任何数据的连接
        // 'heartbeat_check_interval' => 60,
        // 'heartbeat_idle_time' => 600
    ];

    /**
     * 当WebSocket客户端与服务器建立连接并完成握手后会回调此函数。
     * @param $server
     * @param $request
     */
    public function onOpen($server, $request)
    {
        $socket_client_id = $request->fd; //客户端标识id
    }

    /**
     * 当收到来自客户端的数据帧时会回调此函数.
     * @param $server
     * @param $frame
     * @return bool|void
     */
    public function onMessage($server, $frame)
    {
        $socket_client_id = $frame->fd; //客户端标识id
        echo '客户端:' . $socket_client_id . '触发发送消息。' . PHP_EOL;
    }

    /**
     * 绑定客户端id与业务id关联, 存储到cache保证信息准确推送
     * @param $socket_client_id
     * @return bool
     */
    public function saveClientId($socket_client_id, $param)
    {
        //连接保持12小时
        cache('param_key-' . $param, $socket_client_id);
    }

    /**
     * 根据业务id, 获取客户端连接id编号.
     * @param $param_key
     */
    public function getClientId($param_key)
    {
        return cache('param_key-' . $param_key);
    }

    //连接关闭时回调函数
    public function onClose($server, $fd)
    {
        echo "客户端:{$fd}关闭了连接" . PHP_EOL;
    }

    //进行指定目标客户端推送触发
    public function onRequest($request, $response)
    {
        $socket_client_id = $request->fd; //客户端标识id

        $this->swoole->push($socket_client_id, json_encode([
            'status' => true,
        ], JSON_UNESCAPED_UNICODE));
    }
}
